﻿#region Creditos

/* Autor: Edilberto Sánchez Forero	*/
/* Email: esanchezfo@gmail.com		*/
/* Licencia: LGPL, Software Libre	*/
/* País: Colombia, Bogotá			*/

#endregion

#region Librerias

using System;
using System.Collections.Generic;
using System.Data;

using ESF.General;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Text;

#endregion


namespace ESF.Data
{	
	public class DbWriter : DbCommon
	{
		#region Constructor
		
		private DbWriter () 
		{
		}
		
		
		public DbWriter (string pConnectionName, params string [] pParams) : base (pConnectionName, pParams) 
		{
		}
		
		#endregion
	
		
		#region Ejecucion

		public ContextSingleTransactionScope CreateContextSingleTransactionScope ()
		{
			return CreateContextSingleTransactionScope (IsolationLevel.ReadCommitted);
		}


		public ContextSingleTransactionScope CreateContextSingleTransactionScope (IsolationLevel pIsolationLevel)
		{
			return new ContextSingleTransactionScope (ConnectionName, pIsolationLevel);
		}

		
		public int Execute (IDbCommand pCommand, NameValueCollection pPartErrorMsg_ClientMsg = null)
		{
			return Execute (new List<IDbCommand> () { pCommand }, pPartErrorMsg_ClientMsg);
		}
				
		
		public int Execute (params IDbCommand [] pdbcCommands) 
		{
			if (DataHelper.IsEmpty (pdbcCommands))
			{
				return 0;
			}

			return Execute (new List<IDbCommand> (pdbcCommands));
		}


		public int Execute (List<IDbCommand> pdbcCommands) 
		{
			return Execute (pdbcCommands, null);
		}


		public int Execute(List<IDbCommand> pdbcCommands, NameValueCollection pPartErrorMsg_ClientMsg)
		{
			IDbConnection cnn = null;
			IDbTransaction tran = null;

			IDbCommand currentCmd = null;

			StringBuilder stbLog = new StringBuilder();

			Stopwatch stopWatch = new Stopwatch();

			bool useContext = false;

			int totalRowsAffected = 0;


			if (DataHelper.IsEmpty(pdbcCommands)) { return -1; }


			StartExec(stbLog, stopWatch);

			try
			{
				useContext = ContextSingleTransactionScope.GetCurrentTransaction(ConnectionName, out tran, out cnn, ConnectionStringParams);

				for (int i = 0; i < pdbcCommands.Count; i++)
				{
					RegCmdExec(stbLog, pdbcCommands[i]);

					currentCmd = pdbcCommands[i];

					currentCmd.Connection = cnn;

					currentCmd.Transaction = tran;

					totalRowsAffected += currentCmd.ExecuteNonQuery();
				}

				// Debe finalizarla quien la convoco
				if (!useContext)
				{
					tran.Commit();
				}

				stopWatch.Stop();
			}
			catch (Exception pEx)
			{
				throw new DbGenericException(ProviderName, currentCmd, pEx, pPartErrorMsg_ClientMsg);
			}
			finally
			{
				EndExec(stbLog, stopWatch);

				if (!useContext)
				{
					Stop(currentCmd, ProviderName, pPartErrorMsg_ClientMsg);
				}
			}

			return totalRowsAffected;
		}
		
		
		public T ExecuteScalarSQLText<T> (string pSQLCommand)
		{
			return ExecuteScalar<T> (CreateCommand (pSQLCommand));
		}
		
		
		public T ExecuteScalar<T> (IDbCommand pCommand)
		{
			object result;
			
			StringBuilder stbLog = new StringBuilder ();
			
			Stopwatch stopWatch = new Stopwatch ();

			IDbConnection cnn = null;
			IDbTransaction tran = null;
			
			bool useContext;

		
			if (pCommand == null) { return default (T); }


			StartExec (stbLog, stopWatch);
			
			try
			{
				useContext = ContextSingleTransactionScope.GetCurrentTransaction(ConnectionName, out tran, out cnn, ConnectionStringParams); 
				
				RegCmdExec(stbLog, pCommand);

				AddNotDefinedParametersAsNull(pCommand);
				AdjustParametersCommandQuestionMark(pCommand);

				pCommand.Connection = cnn;

				pCommand.Transaction = tran;
				
				result = pCommand.ExecuteScalar ();

				if (!useContext)
				{
					tran.Commit();
				}

				if (Log.IsDebugLogEnabled)
				{
					Log.WriteLineDebug ("Type read: {0}, value read: {1}", (result == null ? "NULL" : result.GetType ().ToString ()), result);
				}

				try
				{
					return (T) result;
				}
				catch (Exception pEx)
				{
					throw new Exception (string.Format ("Format error, expected {0}. Type read: {1}, value read: {2}", typeof (T), (result == null ? "NULL" : result.GetType ().ToString ()), result), pEx);
				}
			}
			catch (Exception pEx)
			{
				throw new DbGenericException(ProviderName, pCommand, pEx);
			}
			finally
			{
				EndExec (stbLog, stopWatch);

				Stop(pCommand, ProviderName, null);
			}
		}
		
		#endregion
	}
}
